import ctypes
import os
import tempfile
from pathlib import Path
from typing import Tuple, Optional, Callable, List

class KeyParse:
    def __init__(self, lib_path: str = None, verbose: bool = False, debug: bool = False):
        """
        初始化KeyParse库
        
        Args:
            lib_path: 共享库路径，如果为None则尝试默认路径
            verbose: 是否启用详细输出
            debug: 是否启用调试输出
        """
        if lib_path is None:
            # 尝试常见路径，包括父目录
            script_dir = os.path.dirname(os.path.abspath(__file__))
            parent_dir = os.path.dirname(script_dir)
            
            possible_paths = [
                "./libkeyparse.so",
                "../libkeyparse.so",  # 父目录
                "/usr/local/lib/libkeyparse.so",
                os.path.join(script_dir, "libkeyparse.so"),
                os.path.join(parent_dir, "libkeyparse.so")  # 父目录的绝对路径
            ]
            
            for path in possible_paths:
                if os.path.exists(path):
                    lib_path = path
                    if verbose:
                        print(f"Found library at: {path}")
                    break
            else:
                # 打印所有尝试过的路径以便调试
                print("Tried the following paths:")
                for path in possible_paths:
                    print(f"  {path}")
                raise FileNotFoundError("Cannot find libkeyparse.so library file")
        
        self.lib = ctypes.CDLL(lib_path)
        self.verbose = verbose
        self.debug = debug
        
        # 定义函数原型
        self._setup_function_prototypes()
        
        # 初始化句柄
        self.handle = self.lib.keyparse_init()
        if not self.handle:
            raise RuntimeError("Failed to initialize KeyParse")
        
        # 设置日志回调
        if verbose or debug:
            log_callback_type = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p)
            self._log_callback = log_callback_type(self._log_handler)
            self.lib.keyparse_set_log_callback(self._log_callback)
    
    def _setup_function_prototypes(self):
        """设置C函数的参数和返回类型"""
        self.lib.keyparse_init.restype = ctypes.c_void_p
        self.lib.keyparse_init.argtypes = []
        
        self.lib.keyparse_process.argtypes = [
            ctypes.c_void_p, 
            ctypes.c_char_p, 
            ctypes.POINTER(ctypes.c_char_p), 
            ctypes.POINTER(ctypes.c_char_p)
        ]
        self.lib.keyparse_process.restype = ctypes.c_int
        
        self.lib.keyparse_process_file.argtypes = [
            ctypes.c_void_p,
            ctypes.c_char_p,
            ctypes.c_char_p
        ]
        self.lib.keyparse_process_file.restype = ctypes.c_int
        
        self.lib.keyparse_free.argtypes = [ctypes.c_void_p]
        self.lib.keyparse_free.restype = None
        
        self.lib.keyparse_free_string.argtypes = [ctypes.c_char_p]
        self.lib.keyparse_free_string.restype = None
        
        self.lib.keyparse_set_log_callback.argtypes = [ctypes.c_void_p]
        self.lib.keyparse_set_log_callback.restype = None
        
        self.lib.keyparse_error_message.argtypes = [ctypes.c_int]
        self.lib.keyparse_error_message.restype = ctypes.c_char_p
    
    def _log_handler(self, level: int, message: ctypes.c_char_p):
        """处理C库的日志消息"""
        level_str = {
            0: "DEBUG",
            1: "INFO", 
            2: "WARNING",
            3: "ERROR"
        }.get(level, "UNKNOWN")
        
        msg = message.decode('utf-8') if message else ""
        
        if (self.debug and level_str == "DEBUG") or (self.verbose and level_str != "DEBUG"):
            print(f"[{level_str}] {msg}")
    
    def process(self, log_line: str) -> Optional[Tuple[str, str]]:
        """
        处理单条日志
        
        Args:
            log_line: 日志字符串
            
        Returns:
            包含(group_key, template)的元组，如果处理失败则返回None
        """
        group_key = ctypes.c_char_p()
        template_str = ctypes.c_char_p()
        
        result = self.lib.keyparse_process(
            self.handle,
            log_line.encode('utf-8'),
            ctypes.byref(group_key),
            ctypes.byref(template_str)
        )
        
        if result == 0:  # KEYPARSE_SUCCESS
            # 获取结果并转换为Python字符串
            gk = ctypes.string_at(group_key).decode('utf-8') if group_key else ""
            ts = ctypes.string_at(template_str).decode('utf-8') if template_str else ""
            
            # 释放C分配的内存
            if group_key:
                self.lib.keyparse_free_string(group_key)
            if template_str:
                self.lib.keyparse_free_string(template_str)
                
            return gk, ts
        else:
            error_msg = self.lib.keyparse_error_message(result)
            if self.verbose:
                print(f"Error processing log: {error_msg}")
            return None
    
    def process_file(self, input_file: str, output_file: str) -> int:
        """
        批量处理日志文件
        
        Args:
            input_file: 输入文件路径
            output_file: 输出CSV文件路径
            
        Returns:
            成功处理的日志条数
        """
        if not os.path.exists(input_file):
            raise FileNotFoundError(f"Input file does not exist: {input_file}")
            
        # 确保输出目录存在
        output_dir = os.path.dirname(output_file)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir)
            
        result = self.lib.keyparse_process_file(
            self.handle,
            input_file.encode('utf-8'),
            output_file.encode('utf-8')
        )
        
        return result
    
    def process_multiple_files(self, input_files: List[str], output_file: str) -> int:
        """
        处理多个输入文件，输出到单个文件
        
        Args:
            input_files: 输入文件路径列表
            output_file: 输出CSV文件路径
            
        Returns:
            成功处理的日志条数
        """
        # 创建一个临时文件来合并所有输入
        with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as temp_file:
            temp_filename = temp_file.name
            
            # 将所有输入文件的内容写入临时文件
            for input_file in input_files:
                if not os.path.exists(input_file):
                    print(f"Warning: Input file does not exist: {input_file}")
                    continue
                    
                with open(input_file, 'r') as f:
                    content = f.read().strip()
                    temp_file.write(content)
                    temp_file.write("\n")  # 添加分隔符
        
        try:
            # 处理合并后的文件
            count = self.process_file(temp_filename, output_file)
            return count
        finally:
            # 清理临时文件
            try:
                os.unlink(temp_filename)
            except:
                pass  # 忽略删除错误
    
    def __del__(self):
        """析构函数，释放资源"""
        if hasattr(self, 'handle') and self.handle:
            self.lib.keyparse_free(self.handle)

# 使用示例可以删除，如果您不需要它